Hi Ray,
Please use the latest Test Release 4.33l for development. There have been many fixes and improvements to the .NET libraries and examples since V4.32.
You should rebuild the debug libraries if any are missing.
All the binaries should reside in either the \KMotion\Release or \KMotion\Debug so they can find each other.
To Debug select Debug Configuration in VS, set break points, run or Step through code.
Regards TK
Group: DynoMotion |
Message: 11697 |
From: Tom Kerekes |
Date: 6/14/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Hi Ray,
It shouldn't matter.
Regards TK
Group: DynoMotion |
Message: 11700 |
From: himykabibble |
Date: 6/14/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Tom,
With 4.33i Release, I get exactly the same behavior - SimpleForm always wierds out after two Version commands.. With 4.33i Debug, I can execute more commands before it wierds out (sometimes as many as 10), but it always wierds out in the same manner as the Release version eventually.
I'll try debugging in a bit...
Regards, Ray L.
|
|
Group: DynoMotion |
Message: 11701 |
From: himykabibble |
Date: 6/14/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
I must be missing some setting.... I set a breakpoint on the KM.WriteLineWithEcho(Command.Text); line in SendCommand_Click. When I click Send it breaks on that line. I then hit F11 (Step Into), and it skips over the line to the next line!
Regards, Ray L.
|
|
Group: DynoMotion |
Message: 11703 |
From: himykabibble |
Date: 6/16/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Any ideas? I'm dead in the water here....
|
|
Group: DynoMotion |
Message: 11705 |
From: Tom Kerekes |
Date: 6/16/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Hi Ray,
Please use Test Version 4.33l ('l' not 'i').
I'm not able to reproduce the problem. I did the following:
#1 running lenovo laptop AMD A6 W8.1 64 #2 fresh install of KMotion433l #3 connect KFLOP (USB Powered)
#3 flash New Version then exit KMotion.exe
#4 cycle power (remove/reconnect USB)
#5 run \Release\SimpleFormsCS.exe #6 push Send "Version" 100 times
Also tried \Debug\SimpleFormsCS.exe 100 times
Upgraded USB drivers to 2014 version included in KMotion433l still can't see any problems.
Maybe there is an issue with your PC? Do you have other KMotion Versions installed on the PC? Any special Windows PATH settings? Did you install dlls to the GAC? Maybe an issue with .NET? CAn you run KMotion.exe and send Version many times without error?
Regards TK
Group: DynoMotion |
Message: 11706 |
From: Tom Kerekes |
Date: 6/16/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Hi Ray,
That is more of a Visual Studio Question. Google Visual Studio Stepping into C++ or unmanaged code. Such as:
Regards
TK
Group: DynoMotion |
Message: 11714 |
From: himykabibble |
Date: 6/17/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
It appears I am screwed.... VisualStudio 2013 Community does not support debugging of unmanaged code. Am I the only one who finds the example PC apps don't work?
Regards, Ray L.
|
|
Group: DynoMotion |
Message: 11715 |
From: TK |
Date: 6/18/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Hi Ray,
What makes you say that? I believe VS Community 2013 is supposed to be the same as the full VS Pro Version.
Have you tested if the pre-compiled binaries run correctly?
I'm not aware of anyone else having trouble with the examples.
Regards TK
It appears I am screwed.... VisualStudio 2013 Community does not support debugging of unmanaged code. Am I the only one who finds the example PC apps don't work?
Regards, Ray L.
|
|
Group: DynoMotion |
Message: 11716 |
From: himykabibble |
Date: 6/18/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Tom,
I can find no option for enabling unmanaged code debugging. It is supposed to be in the Solution properties, Debug tab, and it's not there. I did find numerous references for the Express versions indicating that unmanaged debugging was explicitly disabled.
Yes, I have run the pre-compiled binaries, both Debug and Release, and all beahve the same way. The Debug versions will run slightly longer before going wonky, but none of them run for long before throwing exceptions and ceasing to function. Both 4.32 and 4.33i behave exactly the same way.
Regards, Ry L.
|
|
Group: DynoMotion |
Message: 11717 |
From: himykabibble |
Date: 6/18/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
The same thing happens with v430, which is the version I've been using on the machine for a long time. I can do whatever I want KMotion.exe with no problems, so this appears to be something in the dotNet interface. One more thing I will try today is running the sample apps on my machines PC, which runs v430 under Win7, whereas I'm having these problem on mu laptop, which is Win8.1.
Regards, Ray L.
|
|
Group: DynoMotion |
Message: 11718 |
From: himykabibble |
Date: 6/18/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
One other data point - If I open KMotion, it works fine. I then open SimpleFormCS, and click Send a few times. It hangs. At that point, KMotion is also hung, and only comes back to life after I close SimpleFormCS.
Regards, Ray L.
|
|
Group: DynoMotion |
Message: 11719 |
From: himykabibble |
Date: 6/18/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Tom,
Hate to tell you, but I get EXACTLY the same result, running on my machines PC. Different computer, different OS (Win7 vs Win8.1), different KFlop board, different KMotion version (v4.30 vs v4.32 and v4.33i). This CAN'T be just me....
Regards, Ray L.
|
|
Group: DynoMotion |
Message: 11720 |
From: Tom Kerekes |
Date: 6/18/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Hi Ray,
I remember now that CheckIsReady .NET issue was fixed in Version 4.33j. See:
I previously asked you to use Version 4.33l not 4.33i but you didn't seem to read that part. 'l' = lower case "L"
CheckIsReady might not have been the best example thing to start with as most applications would never use it. Normally an App would know exactly what to expect back from KFLOP for any request it made. But with the Console Screen case where user are just typing random script commands and we don't know what to expect back we just keep reading until we see "Ready".
I tested Visual Studio 2013 Community for debug stepping into the libraries and noticed at first it would not step into them until after I re-built the libraries. I believe the .pdb (Program Database) files are needed.
#1 Fresh install of 4.33l
#2 open/upgrade BuildAllLibs.sln in VS2013
#3 change line (~333) in \TCC67\tcc.c (to fix new incompatibility conflict with new compiler libs)
from
#if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__) to
#if (defined(WIN32) && (_MSC_VER < 1800)) || defined(TCC_UCLIBC) || defined(__FreeBSD__)
#4 Rebuild Solution Debug and Release
#5 open/upgrade SimpleFormsCS.sln with VS2013.sln
#6 right click SimpleFormsCS project | Properties | check Enable Native Code Debugging
#7 set breakpoint at KM = new KMotion_dotNet.KM_Controller();
#8 run + hit breakpoint + Step into (works !!)
#9 "step over" down to KM_dotnet_Interop_New(ref _InstanceHandle, _BoardNumber);
#10 "step into" (works!!!)
HTH Regards TK
Group: DynoMotion |
Message: 11722 |
From: himykabibble |
Date: 6/18/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Tom,
Yes, I read your post as 'i' not 'l', in part due to this God-awful new Yahoo interface.... You can't select text in a message you're writing? WTF are they thinking?? The old I/F was awful. This new one makes awful look good in comparison...
Anyway, I'm installing 4.33 ELL now.
"CheckIsReady might not have been the best example thing to start with as most applications would never use it. Normally an App would know exactly what to expect back from KFLOP for any request it made. But with the Console Screen case where user are just typing random script commands and we don't know what to expect back we just keep reading until we see "Ready"."
What I've been after all along, per the title of the thread, is understanding how to gracefully handle USB disconnects, the way KMotion does. With my current app, the app crashes - not good! I was told to look at the dotNEt examples, and SimpleForm seemed the closest to what I wanted, but now I'm confused, as you seem to be telling me CheckReady is not the way to go. So what IS the right way to go? How does KMotion do it, or, more to the point, how would you implement KMotion using dotNet to get the same robust behavior? I spent a huge amount of time on it before, and couldn't come up with anything that worked.
Regards, Ray L.
|
|
Group: DynoMotion |
Message: 11723 |
From: himykabibble |
Date: 6/18/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Tom,
With 433l, the apps seem happy, and DLL debugging is working. Thanks for figuring that out.
One step missing from your instructions - You have to download and install a VS add-on to support non-Unicode character sets used by the MFC apps.
Now, on to my real problem?
Regards, Ray L.
|
|
Group: DynoMotion |
Message: 11724 |
From: Tom Kerekes |
Date: 6/18/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Hi Ray,
CheckIsReady is unrelated to how to handle USB Connects/Disconnects. As I tried to explain previously CheckIsReady it only relates to the special case where a User enters Random Script commands and you want to send them to KFLOP and display the returned strings including the final "Ready" String. CheckIsReady doesn't have anything to do with whether the USB connection or KFLOP is connected and ready.
So we still recommend for you to see how SimpleFormsCS handles USB being connected an disconnected. The basic strategy is something like:
#1 for all status every windows timer (~ 100ms) checks with if (KM.WaitToken(100) == KMOTION_TOKEN.KMOTION_LOCKED). This will immediately fail if no boards have been present or the board has been disconnected so don't attempt to update any status. If a board is present it should be able to get control of the board within 100ms unless some other App is being a real Hog of KFLOP and not releasing the token. So if this is successful then read all your status, release the Token, and update all your screens. Note that if while reading status the board disconnects one of the reading status calls will correctly create an error. No further status reads should then ever be attempted until the WaitToken again succeeds indicating the board has somehow re-connected.
#2 any button or action to do something to KFLOP (run job, jog, etc) will fail if KFLOP is disconnected. Your App should expect that and if you are doing a sequence of things to KFLOP the first detected error should prevent any further actions to KFLOP.
#3 You App should never lock the Token and never return it. If you do so then other Apps like KMotion.exe are likely to hang and lock up. Some library commands like WriteLineReadLine lock the Token internally. If you kill your Threads while they are making such a call there is a chance of leaving the Token Locked forever. Request your Threads to terminate themselves in a clean manner to avoid this.
HTH Regards TK
Group: DynoMotion |
Message: 11725 |
From: himykabibble |
Date: 6/19/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Tom,
Thanks, I think that makes it pretty clear, and is more or less what I had in mind. I notice though that the SimpleForm example basically decides whether the board is there or not by simply looking at the number of boards returned by a call to KM.GetBoards, and that appears to work well on its own. Can that be used to set/clear a flag that indicates to the rest of the app whether the board is available or not? Can all of the library calls be counted on to return some specific exception if the connection is lost? I don't see any documentation that details what exceptions can be returned by each call. Is studying the dotNet source code the only way to get this?
I am unclear on one thing - the use of the lock. When is it necessary to get the lock, and when is it not? I notice, for example, in the SImpleForm example that timer1_Tick gets the lock to make the MainStatus call, but there are other places where WriteLine and other calls are made without getting the lock. When is it really required?
Regards, Ray L.
|
|
Group: DynoMotion |
Message: 11726 |
From: Tom Kerekes |
Date: 6/19/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Hi Ray,
I'm not sure if KM.GetBoards would be sufficient. Actually now that I think about it I'm not sure how expensive of a call KM.GetBoards. Why not do it the way I suggested? You might also set a flag on expected availability based on that, but you should realize a disconnect could happen at any time so such a flag is of only limited value. I can't see a reason to treat any exception differently. They should all boil down to not being able to communicate to KFLOP.
The idea of the KMotionLock is that when a command (or sequence of commands) is sent to KFLOP and some response is expected it is necessary to guarantee that the issuer of the command receives the response and not somebody else. So the general sequence should be:
Lock -> Write Commands Lines -> Read Responses -> Unlock
The common case of sending one command and receiving one response cans use WriteLineReadLine and has the locking built in.
Writing one command (WriteLine) is atomic and does not need any locking if there is no response to the command.
Regards TK
Group: DynoMotion |
Message: 11730 |
From: himykabibble |
Date: 6/19/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Tom,
OK, I think for the first time, it's finally sinking in....
Please check my understanding:
1) My primary data source will be MainStatus, so wrap the MainStatus call, and perhaps a few other calls needed for the periodic GUI updates, with WaitToken/ReleaseToken as necessary (see #4 below).
2) Whenever an exception occurs, check the exception, and handle the few that may be "fixable" (I'm sure there must be some that can be treated as "soft" errors, if not ignored entirely...). For all others (the majority of exceptions, I would expect), simply abort the operation, set a "BoardHasGoneMissing" flag, and inhibit all board-related GUI activities until the board comes back, and the flag is cleared.
3) Whenever the "BoardHasGoneMissing" flag is set, all other calls are suspended until a MainStatus call is completed successfully, at which time the flag is cleared, and everything can return to normal.
4) WriteLine, and WriteLineReadLine are self-locking, so can be called anytime/anywhere without grabbing the lock. Ditto for any calls that do not generate any response. All other calls require grabbing the lock.
5) Always, always, always, make sure the lock is released in a timely manner, no matter what path is taken through the code.
If that is correct, then I think it is now clear, and I can proceed fairly easily.
BTW - The only reason I asked about KM.GetBoards is that is the mechanism SImpleFormCS uses to detect a disconnect, and change the text in the window frame. Only AFTER this does it try to get the lock and do a GetStatus call. What you describe now is slightly simpler, and sounds like it should be functionally equivalent.
I'm hoping to make the communications between the GUI thread and my "KMotion thread" simpler than in my first app by using message and buffer queues, to pass data back and forth, so I don't have to mess with thread crossings as much as I did before. That way, few, if any, locks/semaphores/mutexes/Invokes/etc. should be required, and it should be easy to avoid potential deadlocks. The GUI thread will send request messages to the KMotion thread through a message queue, and the KMotion thread will carry out the request, and, if appropriate, send a message or data buffer back through a separate response queue. Each message/buffer/whatever will have one, and only one, clearly defined "owner" at any point in time, and each thread either hands the buffer back to the other side, or releases it, as and when appropriate. Perhaps a bit "old school", but should be simple and robust.
Regards, Ray L.
|
|
Group: DynoMotion |
Message: 11732 |
From: himykabibble |
Date: 6/20/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Tom,
I think I'm now seeing a simple way of keeping everything happy in the GUI, using BackgroundWorker threads for communicating with the KFlop. If I understand the threading issues around the KFlop correctly, as long as I properly use the Lock properly, along with WriteLine and WriteLineReadLine, the Kflop will be happy dealing with multiple BackgroundWorker threads, correct? If so, then I think the app becomes very straight-forward, using the Update and Complete methods of the BackgroundWorkers for handling all the GUI updates generated by the actions of the worker threads.
I've already got a skeletal app up and running that cleanly handles connects and disconnects, and currently has several threads making asynchronous requests from the KFlop, updating numerous GUI elements, etc. .including several threads updating a single textBox control. It's all working perfectly so far. Assuming this approach works, this app will be FAR simpler than my first one, and will take FAR less time to develop, as I can re-use large portions of the UI code from the first one.
Regards, Ray L.
|
|
Group: DynoMotion |
Message: 11733 |
From: Tom Kerekes |
Date: 6/21/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Hi Ray,
That all sounds great (including your previous post items).
But to be honest I don't really understand the need or benefit for worker threads at all (other than the GCode Interpreter Thread that is automatically created when GCode is launched). KMotionCNC doesn't use any. It has one GUI Thread and that's it which keeps things simple. I'm no C# or GUI expert but I would expect that updating the GUI with multiple Threads won't see any benefit. I could well be wrong and would love to understand this better.
Potentially KFLOP Communication could theoretically be overlapped with GUI updates using one thread for each providing some benefit. But it seems to me that would only make a difference if the update rate was so fast that the Communication Time + the GUI Update Time was less than the Sample Time.
Keep us posted :} Regards TK
Group: DynoMotion |
Message: 11734 |
From: eric_kato_sanders |
Date: 6/21/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Hi Ray, I appologize in advance if you already know this and I'm not interpreting what you are doing correctly, but updating GUI items directly from a thread is verboten. You can send messages to GUI items, but you cannot safely use GUI control references in a thread. Eric
|
|
Group: DynoMotion |
Message: 11735 |
From: himykabibble |
Date: 6/21/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Tom,
It can be done with a single thread, but with a complex app, it can become difficult to keep it responsive. Using multiple threads can also simplify the code, since certain tasks run with a fixed, simpler function, and essentially autonomously. The BackgroundWorker was created specifically to be used as secondary threads for a GUI application, and greatly simplify the handling of multiple threads, since it has in-built functions for reporting back progress and completion status. At a minimum, it makes sense to have one worker thread to handle the periodic GUI updates, and another to deal with the KFlop. The main GUI thread then has really nothing to do but deal with user events. Time-consuming operations, like loading the G-code file, are also obvious candidates, since using a worker thread can allow the user to, for instance, continue setting up the machine or the tool table while the file is being loaded. Multi-threading is ripe with hazards, but the worker thread concept eliminates, or quietly deals with them, without the user having to worry about them as much.
I've now gone through all the functions I had in my old app that communicate with or use the KFlop or KFlop-derived data, and there is really a pretty small number of basic low-level operations in there. As my old app did not use MainStatus (it was not working right in dotNet when I wrote the app), many of the old functions now revert to simple accesses to the last MainStatus data.
One question though, re: locking - Using dotNet, do ALL calls other than WriteLineReadLine require grabbing the lock? It appears to me there are some, for instance CurrentStatus.GetKFlopBitState(), that I suspect only access data within KMController, and don't communicate with the KFlop at all, so should not require grabbing the lock. How do I know for certain when use of the lock is necessary, and when it is not?
Regards, Ray L.
|
|
Group: DynoMotion |
Message: 11736 |
From: Tom Kerekes |
Date: 6/21/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Hi Ray,
Regarding KMotion WaitToken: Locking should only be required if you are invoking low level script commands to KFLOP yourself. The higher level helper classes should have any locking built in and handle that all for you.
You should be aware that the KMotion_dotNet (and underlying libraries) are not necessarily Thread safe. The WaitToken will allow synchronized communication with KFLOP to keep communications to KFLOP from getting mixed up but that's it. For example if you have one Thread working to alter and update internal library member variables, axis definitions, status, etc..., and another Thread reading it at the same time, there are some potential hazards.
Regards TK
Group: DynoMotion |
Message: 11754 |
From: himykabibble |
Date: 6/23/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Tom,
OK, I think I understand. My KMotion requests would be effectively serialized, regardless of which thread initiated them, so I don't think any actual threading problems should materialize.
I've spent the last day having fun with GUI design - getting all the controls to re-size properly when the window is re-sized. What a colossal PITA! Most simple controls (Buttons, etc.) will re-size well automatically, but TextBox (like DROs) and Label controls - not so much. For the DROs, I found the only viable solution was to use RichTextBox controls, and add SizeChanged handlers that calculate new Height, Width, Margin, and Font.Size values on-the-fly.
Regards, Ray L.
|
|
Group: DynoMotion |
Message: 11755 |
From: himykabibble |
Date: 6/23/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Eric,
Understood. That is precisely the reason for using BackgroundWorker threads - they have built-in methods for, in effect, making callbacks to the GUI thread to give progress updates and completion status. Those callbacks can then update the GUI, and will always execute in the GUI thread itself, so the updates are completely "safe".
Regards, Ray L.
|
|
Group: DynoMotion |
Message: 11756 |
From: himykabibble |
Date: 6/23/2015 |
Subject: Re: Gracefully Handling USB Disconnect |
Good God! This new Yahoo interface sucks a$$! The last two responses (from Tom and Eric) only showed up here today, even though they were posted two days ago!
Regards, Ray L.
|
|
| | | | | | | | | | | | | | | | | |